
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
// 
//   http://www.apache.org/licenses/LICENSE-2.0
// 
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

/**
 * AUTO-GENERATED FILE. DO NOT MODIFY.
 */

// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
// 
//   http://www.apache.org/licenses/LICENSE-2.0
// 
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.
import { __extends } from 'tslib';
import * as graphic from '../../util/graphic.js';
import { toggleHoverEmphasis } from '../../util/states.js';
import HeatmapLayer from './HeatmapLayer.js';
import * as zrUtil from 'zrender/lib/core/util.js';
import ChartView from '../../view/Chart.js';
import { isCoordinateSystemType } from '../../coord/CoordinateSystem.js';
import { setLabelStyle, getLabelStatesModels } from '../../label/labelStyle.js';

function getIsInPiecewiseRange(dataExtent, pieceList, selected) {
	var dataSpan = dataExtent[1] - dataExtent[0];
	pieceList = zrUtil.map(pieceList, function (piece) {
		return {
			interval: [(piece.interval[0] - dataExtent[0]) / dataSpan, (piece.interval[1] - dataExtent[0]) / dataSpan]
		};
	});
	var len = pieceList.length;
	var lastIndex = 0;
	return function (val) {
		var i; // Try to find in the location of the last found

		for (i = lastIndex; i < len; i++) {
			var interval = pieceList[i].interval;

			if (interval[0] <= val && val <= interval[1]) {
				lastIndex = i;
				break;
			}
		}

		if (i === len) {
			// Not found, back interation
			for (i = lastIndex - 1; i >= 0; i--) {
				var interval = pieceList[i].interval;

				if (interval[0] <= val && val <= interval[1]) {
					lastIndex = i;
					break;
				}
			}
		}

		return i >= 0 && i < len && selected[i];
	};
}

function getIsInContinuousRange(dataExtent, range) {
	var dataSpan = dataExtent[1] - dataExtent[0];
	range = [(range[0] - dataExtent[0]) / dataSpan, (range[1] - dataExtent[0]) / dataSpan];
	return function (val) {
		return val >= range[0] && val <= range[1];
	};
}

function isGeoCoordSys(coordSys) {
	var dimensions = coordSys.dimensions; // Not use coordSys.type === 'geo' because coordSys maybe extended

	return dimensions[0] === 'lng' && dimensions[1] === 'lat';
}

var HeatmapView =
/** @class */
function (_super) {
	__extends(HeatmapView, _super);

	function HeatmapView() {
		var _this = _super !== null && _super.apply(this, arguments) || this;

		_this.type = HeatmapView.type;
		return _this;
	}

	HeatmapView.prototype.render = function (seriesModel, ecModel, api) {
		var visualMapOfThisSeries;
		ecModel.eachComponent('visualMap', function (visualMap) {
			visualMap.eachTargetSeries(function (targetSeries) {
				if (targetSeries === seriesModel) {
					visualMapOfThisSeries = visualMap;
				}
			});
		});

		if (process.env.NODE_ENV !== 'production') {
			if (!visualMapOfThisSeries) {
				throw new Error('Heatmap must use with visualMap');
			}
		} // Clear previously rendered progressive elements.

		this._progressiveEls = null;
		this.group.removeAll();
		var coordSys = seriesModel.coordinateSystem;

		if (coordSys.type === 'cartesian2d' || coordSys.type === 'calendar') {
			this._renderOnCartesianAndCalendar(seriesModel, api, 0, seriesModel.getData().count());
		} else if (isGeoCoordSys(coordSys)) {
			this._renderOnGeo(coordSys, seriesModel, visualMapOfThisSeries, api);
		}
	};

	HeatmapView.prototype.incrementalPrepareRender = function (seriesModel, ecModel, api) {
		this.group.removeAll();
	};

	HeatmapView.prototype.incrementalRender = function (params, seriesModel, ecModel, api) {
		var coordSys = seriesModel.coordinateSystem;

		if (coordSys) {
			// geo does not support incremental rendering?
			if (isGeoCoordSys(coordSys)) {
				this.render(seriesModel, ecModel, api);
			} else {
				this._progressiveEls = [];

				this._renderOnCartesianAndCalendar(seriesModel, api, params.start, params.end, true);
			}
		}
	};

	HeatmapView.prototype.eachRendered = function (cb) {
		graphic.traverseElements(this._progressiveEls || this.group, cb);
	};

	HeatmapView.prototype._renderOnCartesianAndCalendar = function (seriesModel, api, start, end, incremental) {
		var coordSys = seriesModel.coordinateSystem;
		var isCartesian2d = isCoordinateSystemType(coordSys, 'cartesian2d');
		var width;
		var height;
		var xAxisExtent;
		var yAxisExtent;

		if (isCartesian2d) {
			var xAxis = coordSys.getAxis('x');
			var yAxis = coordSys.getAxis('y');

			if (process.env.NODE_ENV !== 'production') {
				if (!(xAxis.type === 'category' && yAxis.type === 'category')) {
					throw new Error('Heatmap on cartesian must have two category axes');
				}

				if (!(xAxis.onBand && yAxis.onBand)) {
					throw new Error('Heatmap on cartesian must have two axes with boundaryGap true');
				}
			} // add 0.5px to avoid the gaps

			width = xAxis.getBandWidth() + .5;
			height = yAxis.getBandWidth() + .5;
			xAxisExtent = xAxis.scale.getExtent();
			yAxisExtent = yAxis.scale.getExtent();
		}

		var group = this.group;
		var data = seriesModel.getData();
		var emphasisStyle = seriesModel.getModel(['emphasis', 'itemStyle']).getItemStyle();
		var blurStyle = seriesModel.getModel(['blur', 'itemStyle']).getItemStyle();
		var selectStyle = seriesModel.getModel(['select', 'itemStyle']).getItemStyle();
		var borderRadius = seriesModel.get(['itemStyle', 'borderRadius']);
		var labelStatesModels = getLabelStatesModels(seriesModel);
		var emphasisModel = seriesModel.getModel('emphasis');
		var focus = emphasisModel.get('focus');
		var blurScope = emphasisModel.get('blurScope');
		var emphasisDisabled = emphasisModel.get('disabled');
		var dataDims = isCartesian2d ? [data.mapDimension('x'), data.mapDimension('y'), data.mapDimension('value')] : [data.mapDimension('time'), data.mapDimension('value')];

		for (var idx = start; idx < end; idx++) {
			var rect = void 0;
			var style = data.getItemVisual(idx, 'style');

			if (isCartesian2d) {
				var dataDimX = data.get(dataDims[0], idx);
				var dataDimY = data.get(dataDims[1], idx); // Ignore empty data and out of extent data

				if (isNaN(data.get(dataDims[2], idx)) || isNaN(dataDimX) || isNaN(dataDimY) || dataDimX < xAxisExtent[0] || dataDimX > xAxisExtent[1] || dataDimY < yAxisExtent[0] || dataDimY > yAxisExtent[1]) {
					continue;
				}

				var point = coordSys.dataToPoint([dataDimX, dataDimY]);
				rect = new graphic.Rect({
					shape: {
						x: point[0] - width / 2,
						y: point[1] - height / 2,
						width: width,
						height: height
					},
					style: style
				});
			} else {
				// Ignore empty data
				if (isNaN(data.get(dataDims[1], idx))) {
					continue;
				}

				rect = new graphic.Rect({
					z2: 1,
					shape: coordSys.dataToRect([data.get(dataDims[0], idx)]).contentShape,
					style: style
				});
			} // Optimization for large dataset

			if (data.hasItemOption) {
				var itemModel = data.getItemModel(idx);
				var emphasisModel_1 = itemModel.getModel('emphasis');
				emphasisStyle = emphasisModel_1.getModel('itemStyle').getItemStyle();
				blurStyle = itemModel.getModel(['blur', 'itemStyle']).getItemStyle();
				selectStyle = itemModel.getModel(['select', 'itemStyle']).getItemStyle(); // Each item value struct in the data would be firstly
				// {
				//     itemStyle: { borderRadius: [30, 30] },
				//     value: [2022, 02, 22]
				// }

				borderRadius = itemModel.get(['itemStyle', 'borderRadius']);
				focus = emphasisModel_1.get('focus');
				blurScope = emphasisModel_1.get('blurScope');
				emphasisDisabled = emphasisModel_1.get('disabled');
				labelStatesModels = getLabelStatesModels(itemModel);
			}

			rect.shape.r = borderRadius;
			var rawValue = seriesModel.getRawValue(idx);
			var defaultText = '-';

			if (rawValue && rawValue[2] != null) {
				defaultText = rawValue[2] + '';
			}

			setLabelStyle(rect, labelStatesModels, {
				labelFetcher: seriesModel,
				labelDataIndex: idx,
				defaultOpacity: style.opacity,
				defaultText: defaultText
			});
			rect.ensureState('emphasis').style = emphasisStyle;
			rect.ensureState('blur').style = blurStyle;
			rect.ensureState('select').style = selectStyle;
			toggleHoverEmphasis(rect, focus, blurScope, emphasisDisabled);
			rect.incremental = incremental; // PENDING

			if (incremental) {
				// Rect must use hover layer if it's incremental.
				rect.states.emphasis.hoverLayer = true;
			}

			group.add(rect);
			data.setItemGraphicEl(idx, rect);

			if (this._progressiveEls) {
				this._progressiveEls.push(rect);
			}
		}
	};

	HeatmapView.prototype._renderOnGeo = function (geo, seriesModel, visualMapModel, api) {
		var inRangeVisuals = visualMapModel.targetVisuals.inRange;
		var outOfRangeVisuals = visualMapModel.targetVisuals.outOfRange; // if (!visualMapping) {
		//     throw new Error('Data range must have color visuals');
		// }

		var data = seriesModel.getData();
		var hmLayer = this._hmLayer || this._hmLayer || new HeatmapLayer();
		hmLayer.blurSize = seriesModel.get('blurSize');
		hmLayer.pointSize = seriesModel.get('pointSize');
		hmLayer.minOpacity = seriesModel.get('minOpacity');
		hmLayer.maxOpacity = seriesModel.get('maxOpacity');
		var rect = geo.getViewRect().clone();
		var roamTransform = geo.getRoamTransform();
		rect.applyTransform(roamTransform); // Clamp on viewport

		var x = Math.max(rect.x, 0);
		var y = Math.max(rect.y, 0);
		var x2 = Math.min(rect.width + rect.x, api.getWidth());
		var y2 = Math.min(rect.height + rect.y, api.getHeight());
		var width = x2 - x;
		var height = y2 - y;
		var dims = [data.mapDimension('lng'), data.mapDimension('lat'), data.mapDimension('value')];
		var points = data.mapArray(dims, function (lng, lat, value) {
			var pt = geo.dataToPoint([lng, lat]);
			pt[0] -= x;
			pt[1] -= y;
			pt.push(value);
			return pt;
		});
		var dataExtent = visualMapModel.getExtent();
		var isInRange = visualMapModel.type === 'visualMap.continuous' ? getIsInContinuousRange(dataExtent, visualMapModel.option.range) : getIsInPiecewiseRange(dataExtent, visualMapModel.getPieceList(), visualMapModel.option.selected);
		hmLayer.update(points, width, height, inRangeVisuals.color.getNormalizer(), {
			inRange: inRangeVisuals.color.getColorMapper(),
			outOfRange: outOfRangeVisuals.color.getColorMapper()
		}, isInRange);
		var img = new graphic.Image({
			style: {
				width: width,
				height: height,
				x: x,
				y: y,
				image: hmLayer.canvas
			},
			silent: true
		});
		this.group.add(img);
	};

	HeatmapView.type = 'heatmap';
	return HeatmapView;
}(ChartView);

export default HeatmapView;